/**
  ******************************************************************************
  * @file    bsp.c
  * @author  ashuai0110
  * @version V2.0
  * @date    2024-09-07
  * @brief   板级支持包
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  * Change Logs:
  * Date          Author        Notes
  * 2024-09-07    ashuai0110    完成基本内容
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "bsp.h"

/* 私有宏定义-----------------------------------------------------------------*/

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/

/* 全局变量-------------------------------------------------------------------*/
uint8_t usart1DmaTxBuf[64];
uint8_t usart1DmaRxBuf[64];

/* 私有函数原型---------------------------------------------------------------*/


/**
  * @brief  系统时钟初始化72MHz(HSE)
  *
  * @param  None
  *
  * @retval None
  */
static void rcc_clock_config(void)
{
    RCC_DeInit();

    RCC_HSEConfig(RCC_HSE_ON); /* 打开外部高速时钟HSE */
    while(RESET == RCC_GetFlagStatus(RCC_FLAG_HSERDY)); /* 等待时钟稳定 */

    RCC_HCLKConfig(RCC_SYSCLK_Div1); /* AHB clock(HCLK) = SYSCLK/1 (max:72MHz) */

    RCC_PCLK1Config(RCC_HCLK_Div2); /* APB1 clock(PCLK1) = HCLK/2 (max:36MHz) */

    RCC_PCLK2Config(RCC_HCLK_Div1); /* APB2 clock(PCLK2) = HCLK/1 (max:72MHz) */

    FLASH_SetLatency(FLASH_Latency_2); /* FLASH 2等待周期 */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* 使能FLASH预取缓冲区 */

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* SYSCLK == 72MHz  PLLCLK = 8MHz*9 */
    RCC_PLLCmd(ENABLE); /* 使能PLL */
    while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLLRDY)); /* 等待PLL稳定 */
    
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* 选择PLLCLK作为SYSCLK时钟源 */
    while(0x08 != RCC_GetSYSCLKSource()); /* 等待SYSCLK时钟源切换完成 */

    SysTick_Config(72000); /* systick初始化周期1ms */
}

/**
  * @brief  NVIC初始化
  *
  * @param  None
  *
  * @retval None
  */
static void nvic_config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); /* 设置中断优先级组4 */
    
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/**
  * @brief  USART1 DMA初始化
  *
  * @param  txBuf    : 发送缓冲区
  *
  * @param  txBufLen : 发送缓冲区长度
  *
  * @param  rxBuf    : 接收缓冲区
  *
  * @param  rxBufLen : 接收缓冲区长度
  *
  * @retval None
  */
static void usart1_dma_config(uint8_t *txBuf, uint16_t txBufLen, uint8_t *rxBuf, uint16_t rxBufLen)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* 打开DMA时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* 打开串口时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* 打开GPIO时钟 */
    
    /* USART Tx的GPIO配置 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /* 设置引脚号 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /* 设置引脚模式 复用推挽 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* 设置引脚速度 */
    GPIO_Init(GPIOA, &GPIO_InitStructure); /* 初始化GPIO */
    /* USART Rx的GPIO配置 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; /* 设置引脚号 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; /* 设置引脚模式 浮空输入 */
    GPIO_Init(GPIOA, &GPIO_InitStructure); /* 初始化GPIO */

    USART_DeInit(USART1);

    USART_InitStructure.USART_BaudRate = 115200; /* 波特率 */
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* 数据长度 8bit */
    USART_InitStructure.USART_StopBits = USART_StopBits_1; /* 停止位 1bit */
    USART_InitStructure.USART_Parity = USART_Parity_No; /* 校验位 无 */
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; /* 硬件流控 无 */
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* 工作模式 接收和发送 */
    USART_Init(USART1, &USART_InitStructure); /* 初始化串口 */
    
    DMA_DeInit(DMA1_Channel4);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)txBuf;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = txBufLen;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    
    DMA_DeInit(DMA1_Channel5);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rxBuf;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = rxBufLen;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
    /* 使能DMA传输完成和传输错误中断 */
    DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);
    DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
    DMA_ITConfig(DMA1_Channel5, DMA_IT_TE, ENABLE);
    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
    
    DMA_Cmd(DMA1_Channel4, DISABLE); /* 关闭串口1 DMA发送通道 */
    DMA_Cmd(DMA1_Channel5, ENABLE); /* 开启串口1 DMA接收通道 */

    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); /* 开启串口1 DMA发送请求 */
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); /* 开启串口1 DMA接收请求 */
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);; /* 使能空闲中断 */

    USART_Cmd(USART1, ENABLE); /* 开启串口 */
}

/**
  * @brief  BSP初始化
  *
  * @param  None
  *
  * @retval None
  */
void bsp_init(void)
{
    nvic_config();
    rcc_clock_config();
    usart1_dma_config(usart1DmaTxBuf, sizeof(usart1DmaTxBuf), usart1DmaRxBuf, sizeof(usart1DmaRxBuf));
}

/**
  * @brief  USART1 DMA 发送重新初始化
  * @param  num : 数量
  * @retval None
  */
void bsp_usart1_dma_tx_reconfig(uint16_t num)
{
    if(num == 0) { return ; }
    
    DMA_Cmd(DMA1_Channel4, DISABLE);
    DMA_SetCurrDataCounter(DMA1_Channel4, num);
    DMA_Cmd(DMA1_Channel4, ENABLE);
}

/**
  * @brief  USART1 DMA 接收重新初始化
  * @param  num : 数量
  * @retval None
  */
void bsp_usart1_dma_rx_reconfig(uint16_t num)
{
    if(num == 0) { return ; }
    
    DMA_Cmd(DMA1_Channel5, DISABLE);
    DMA_SetCurrDataCounter(DMA1_Channel5, num);
    DMA_Cmd(DMA1_Channel5, ENABLE);
}
